using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Microsoft.Win32.SafeHandles;
using WindowsAPI.Service;

namespace WindowsAPI
{
    [SuppressUnmanagedCodeSecurity, Dll(FileName)]
    public static class hid
    {
        public const string FileName = "hid.dll";

        [DllImport(FileName, SetLastError = true)]
        public static extern void HidD_GetHidGuid(ref Guid hidGuid);

        /// <summary>Routine sends an output report to a top-level collection</summary>
        /// <param name="HidDeviceObject">Specifies an open handle to a top-level collection.</param>
        /// <param name="ReportBuffer">
        /// Pointer to a caller-allocated output report buffer that the caller uses to specify a report ID.
        /// For more information about this parameter, see the Remarks section.
        /// </param>
        /// <param name="ReportBufferLength">
        /// Specifies the size, in bytes, of the report buffer. 
        /// The report buffer must be large enough to hold the output report -- excluding its report ID, 
        /// if report IDs are used -- plus one additional byte that specifies a nonzero report ID or zero.
        /// </param>
        /// <returns>If HidD_SetOutputReport succeeds, it returns TRUE; otherwise, it returns FALSE.</returns>
        [DllImport(FileName, SetLastError = true)]
        public static extern bool HidD_SetOutputReport(SafeFileHandle HidDeviceObject, IntPtr ReportBuffer, ulong ReportBufferLength);

        // var manufacturerString = new StringBuilder(128);
        // var returnStatus = HidD_GetManufacturerString(hidHandle, manufacturerString, manufacturerString.Capacity);
        // if (returnStatus)
        //      Console.WriteLine("Manufacturer name is {0}", manufacturerString.ToString());
        [DllImport(FileName, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool HidD_GetManufacturerString(SafeFileHandle HidDeviceObject, StringBuilder Buffer, Int32 BufferLength);

        [DllImport(FileName, SetLastError = true)]
        public static extern bool HidD_GetFeature(SafeFileHandle HidDeviceObject, ref Byte lpReportBuffer, Int32 ReportBufferLength);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="HidDeviceObject">Specifies an open handle to a top-level collection.</param>
        /// <param name="Attributes">
        /// Pointer to a caller-allocated HIDD_ATTRIBUTES structure that returns the attributes 
        /// of the collection specified by HidDeviceObject.
        /// </param>
        /// <returns>returns TRUE if succeeds; otherwise, it returns FALSE.</returns>
        [DllImport(FileName, SetLastError = true)]
        public static extern bool HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);

        [DllImport(FileName, SetLastError = true)]
        public static extern Boolean HidD_FreePreparsedData(ref IntPtr PreparsedData);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="HidDeviceObject"></param>
        /// <returns>TRUE if it successfully flushes the queue. Otherwise, it returns FALSE</returns>
        [DllImport(FileName, SetLastError = true)]
        public static extern Boolean HidD_FlushQueue(SafeFileHandle HidDeviceObject);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct HIDD_ATTRIBUTES
    {
        public HIDD_ATTRIBUTES Default { get { return new HIDD_ATTRIBUTES { Size = Marshal.SizeOf(typeof(HIDD_ATTRIBUTES)) }; } }

        public int Size;
        public short VendorID;
        public short ProductID;
        public short VersionNumber;

    }
}